home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Peter Lewis / PNL Libraries / MyOOMainLoop.p < prev    next >
Encoding:
Text File  |  1994-10-25  |  30.5 KB  |  1,257 lines  |  [TEXT/PJMM]

  1. unit MyOOMainLoop;
  2.  
  3. interface
  4.  
  5.     uses
  6.         AppleEvents, Drag;
  7.  
  8.     const
  9.         WT_NotMine = 'NtMe';
  10.         WT_Generic = 'Genr';
  11.         bad_window_id = -1;
  12.         kAECloseAll = 'Clos';
  13.  
  14.     type
  15.         SCType = (SCSave, SCCancel, SCDiscard);
  16.         WObject = object
  17.                 window: dialogPtr;
  18.                 resid: integer;
  19.                 window_type: OSType;
  20.                 window_id: longInt;
  21.                 growRect: rect; { minimum/maximum rect size (for use with grow window) }
  22.                 zoomSize: point; { Optimum zoom size }
  23.                 zoomed: boolean;
  24.                 unzoomed: rect;
  25.                 draw_grow_icon: boolean;
  26.                 is_active: boolean;
  27.                 is_default_object: boolean;
  28.                 close_hides_window: boolean;
  29.                 last_event_time: longInt;
  30.                 last_event_modifers: integer;
  31.                 last_event_had_option: boolean;
  32.                 last_event_had_command: boolean;
  33.                 last_event_had_shift: boolean;
  34.                 last_event_had_control: boolean;
  35.                 AppleGuideWindowType: str31;
  36.                 procedure JointCreate (id: integer);
  37.                 procedure Create (id: integer);
  38.                 procedure CreateBehind (id: integer; behind: WindowPtr);
  39.                 procedure Destroy;
  40.                 procedure GetWindowPos (h: handle);
  41.                 procedure SetWindowPos (h: handle; var wasvisible: boolean);
  42.                 function SaveChanges: SCType;
  43.                 procedure DoClose;
  44. { DoClose checks modified things etc, then calls Destroy }
  45.                 function SetMenuBar: boolean;
  46.                 procedure SetMenus;
  47.                 function EditMenuEnabled: boolean;
  48.                 procedure SetEditMenuItem (item: integer);
  49.                 procedure DoEditMenu (item: integer);
  50.                 function GetAESelection (var reply: AppleEvent): OSErr;
  51.                 function GetAEWindow (var windowrec: AERecord): OSErr;
  52.                 function DoMenuKey (er: eventRecord; ch: char): longInt;
  53.                 procedure CalculateRegion (var rgn: rgnHandle);
  54.                 function WaitForEvent (var er: eventRecord; sleep: longInt): boolean;
  55.                 procedure DoIdle;
  56.                 procedure DoDiskEvent (message: longInt);
  57.                 procedure DoSuspendResume (resume: boolean);
  58.                 procedure DoHighLevel (er: eventRecord);
  59.                 procedure DoContent (er: eventRecord);
  60.                 procedure DoKey (modifiers: integer; ch: char; code: integer);
  61.                 procedure DoSpecialKey (modifiers: integer; ch: char; code: integer);
  62.                 procedure DoAutoKey (modifiers: integer; ch: char; code: integer);
  63.                 procedure DoDrag (where: point);
  64.                 procedure DoGrow (where: point);
  65.                 procedure Zoom (zoomout: boolean; fullscreen: boolean);
  66.                 procedure DoZoom (where: point; code: integer);
  67.                 procedure DoGoAway (where: point);
  68.                 procedure DoUpdate;
  69.                 procedure DoMouseMoved (where: point);
  70.                 procedure DrawGrow;
  71.                 procedure DoActivateDeactivate (activate: boolean);
  72.                 procedure TextChanged; { called for paste/clear/cut/key down etc }
  73.                 procedure Resize;
  74.                 procedure InitialZoom (h, v: integer);
  75.                 procedure Draw;
  76.                 function TrackingHandler (message: DragTrackingMessage; dragref: DragReference): OSErr;
  77.                 function ReceiveHandler (dragref: DragReference): OSErr;
  78.                 function DragSend (flavor: FlavorType; item: ItemReference; dragref: DragReference): OSErr;
  79.                 function DoSetupDrag (dragref: DragReference; dragrgn: RgnHandle): OSErr;
  80.                 procedure DoTrackDrag (var er: EventRecord);
  81.                 function DoMainClick (er: eventRecord; wp: windowPtr; code: integer): boolean;
  82.                 function DoIsDialogEvent (er: eventRecord): boolean;
  83.                 function DoDialogSelect (er: eventRecord; var dlg: dialogPtr; var item: integer): boolean;
  84.                 function HandleSimpleEvents (er: eventRecord): boolean;
  85.                 function HandleEvents (er: eventRecord): boolean;
  86.             end;
  87.         DObject = object(WObject)
  88.                 ok_item, cancel_item: integer;
  89.                 handle_activate_outline: boolean;
  90.                 handle_shift_tab: boolean;
  91.                 disable_edit_menu: boolean;
  92.                 procedure Create (id: integer);
  93.                 override;
  94.                 procedure CreateBehind (id: integer; behind: WindowPtr);
  95.                 override;
  96.                 procedure Destroy;
  97.                 override;
  98.                 procedure SetOOOutline (def_item, user_item: integer);
  99.                 procedure DrawOutline;
  100.                 procedure DoActivateDeactivate (activate: boolean);
  101.                 override;
  102.                 function HandleEvents (er: eventRecord): boolean;
  103.                 override;
  104.                 procedure DoItem (item: integer);
  105.                 procedure DoItemWhere (er: eventRecord; item: integer);
  106.                 procedure DoCancel (modifiers: integer; ch: char; code: integer);
  107.                 procedure DoOK (modifiers: integer; ch: char; code: integer);
  108.                 procedure SetEditMenuItem (item: integer);
  109.                 override;
  110.                 function EditMenuEnabled: boolean;
  111.                 override;
  112.                 procedure DoEditMenu (item: integer);
  113.                 override;
  114.                 function DoIsDialogEvent (er: eventRecord): boolean;
  115.                 override;
  116.                 function GetAESelection (var reply: AppleEvent): OSErr;
  117.                 override;
  118.             end;
  119.  
  120.     var
  121.         default_object: WObject;
  122.         edit_menu_always_enabled: boolean;
  123.         has_DragManager: boolean;
  124.  
  125.     function GetWType (wp: windowPtr): OSType;
  126.     function GetWObject (wp: windowPtr): WObject;
  127.     function GetDObject (dlg: dialogPtr): DObject;
  128.     function FrontObject: WObject;
  129.     function IsWObjectFront (o: WObject): boolean;
  130.     function FindWindowID (id: longInt): WObject;
  131.     procedure InitMainLoop (dobj: DObject; domenu: procptr);
  132. { dobj will be used returned with window set to wp whenever GetWObject/GetDObject is called with a DA or nil window }
  133.     procedure FinishMainLoop;
  134. {    procedure DoMenu (themenu, theitem: integer);}
  135.     function InForeground: boolean;
  136.     procedure DoCloseAll (all: boolean);
  137.  
  138. implementation
  139.  
  140.     uses
  141.         AEObjects, AERegistry, Script, Processes, MyMenus, MyTypes, MyFMenus, BaseGlobals, MySystemGlobals, {}
  142.         MyTEUtils, MyAssertions, MyDialogs, MyAEUtils, MyWindows, MyMathUtils, QLowLevel;
  143.  
  144.     const
  145.         titlebar_hight = 18;
  146.  
  147.     const
  148. { from EPPC }
  149.         OOMagic = 'MyOO';
  150.         BadOOMagic = 'bado';
  151.  
  152.     type
  153.         myWindowRecord = record
  154.                 thewindow: windowRecord;
  155.                 magic: OSType;
  156.             end;
  157.         myWindowPtr = ^myWindowRecord;
  158.         myDialogRecord = record
  159.                 thedialog: dialogRecord;
  160.                 magic: OSType;
  161.             end;
  162.         myDialogPtr = ^myDialogRecord;
  163.  
  164.     var
  165.         domenup: procptr;
  166.         last_window_id: longInt;
  167.         in_foreground: boolean;
  168.  
  169.     procedure DoMenu (themenu, theitem: integer; domenu: procptr);
  170.     inline
  171.         $205F, $4E90;
  172.  
  173.     procedure DoCloses (all: boolean);
  174.         var
  175.             fw: WindowPtr;
  176.     begin
  177.         if all then begin
  178.             fw := FrontWindow;
  179.             while fw <> nil do begin
  180.                 FrontObject.DoClose;
  181.                 if fw = FrontWindow then
  182.                     leave;
  183.                 fw := FrontWindow;
  184.             end;
  185.         end
  186.         else begin
  187.             FrontObject.DoClose;
  188.         end;
  189.     end;
  190.  
  191.     function HandleClose (event, reply: AppleEvent; refcon: longInt): OSErr;
  192.         var
  193.             err: OSErr;
  194.     begin
  195.         if FrontWindow <> nil then begin
  196.             DoCloses(refcon <> 0);
  197.             err := noErr;
  198.         end
  199.         else begin
  200.             err := errAENoSuchObject;
  201.         end;
  202.         HandleClose := err;
  203.     end;
  204.  
  205.     procedure DoCloseAll (all: boolean);
  206.     begin
  207.         if has_AppleEvents then begin
  208.             if all then begin
  209.                 SendSelfSimpleEvent(kAECoreSuite, kAECloseAll);
  210.             end
  211.             else begin
  212.                 SendSelfSimpleEvent(kAECoreSuite, kAEClose);
  213.             end;
  214.         end
  215.         else begin
  216.             DoCloses(all);
  217.         end;
  218.     end;
  219.  
  220.     function WObject.TrackingHandler (message: DragTrackingMessage; dragref: DragReference): OSErr;
  221.     begin
  222.         TrackingHandler := -1;
  223.     end;
  224.  
  225.     function MyTrackingHandler (message: DragTrackingMessage; window: WindowPtr; refcon: Ptr; dragref: DragReference): OSErr;
  226.     begin
  227.         MyTrackingHandler := GetWObject(window).TrackingHandler(message, dragref);
  228.     end;
  229.  
  230.     function WObject.ReceiveHandler (dragref: DragReference): OSErr;
  231.     begin
  232.         ReceiveHandler := -1;
  233.     end;
  234.  
  235.     function MyReceiveHandler (window: WindowPtr; refcon: Ptr; dragref: DragReference): OSErr;
  236.     begin
  237.         MyReceiveHandler := GetWObject(window).ReceiveHandler(dragref);
  238.     end;
  239.  
  240.     function WObject.DragSend (flavor: FlavorType; item: ItemReference; dragref: DragReference): OSErr;
  241.     begin
  242.         DragSend := -1;
  243.     end;
  244.  
  245.     var
  246.         drag_obj: WObject;
  247.  
  248.     function MyDragSendProc (flavor: FlavorType; refcon: Ptr; item: ItemReference; dragref: DragReference): OSErr;
  249.     begin
  250.         MyDragSendProc := drag_obj.DragSend(flavor, item, dragref);
  251.     end;
  252.  
  253. {$S Init}
  254.     procedure InitMainLoop (dobj: DObject; domenu: procptr);
  255.         var
  256.             i: integer;
  257.             dummy: boolean;
  258.             dummy_er: eventRecord;
  259.             junk: OSErr;
  260.             gv: longInt;
  261.             err: OSErr;
  262.     begin
  263.         for i := 1 to 5 do
  264.             dummy := EventAvail(everyEvent, dummy_er);
  265.         has_DragManager := (Gestalt(gestaltDragMgrAttr, gv) = noErr) & (BTST(gv, gestaltDragMgrPresent));
  266.         if has_DragManager then begin
  267.             err := InstallTrackingHandler(@MyTrackingHandler, nil, nil);
  268.             err := InstallReceiveHandler(@MyReceiveHandler, nil, nil);
  269.         end;
  270.         domenup := domenu;
  271.         default_object := dobj;
  272.         dobj.window := nil;
  273.         dobj.window_id := bad_window_id;
  274.         dobj.JointCreate(0);
  275.         dobj.is_default_object := true;
  276.         dobj.window_type := WT_NotMine;
  277.         last_window_id := 1;
  278.         edit_menu_always_enabled := false;
  279.         if has_AppleEvents then begin
  280.             junk := AEInstallEventHandler(kAECoreSuite, kAEClose, @HandleClose, 0, false);
  281.             junk := AEInstallEventHandler(kAECoreSuite, kAECloseAll, @HandleClose, 1, false);
  282.         end;
  283.     end;
  284.  
  285. {$S Term}
  286.     procedure FinishMainLoop;
  287.     begin
  288.         dispose(default_object);
  289.     end;
  290.  
  291. {$S}
  292.     function InForeground: boolean;
  293.         var
  294.             gv: longInt;
  295.             ourpsn, frontpsn: ProcessSerialNumber;
  296.             front: boolean;
  297.     begin
  298.         if (Gestalt(gestaltOSAttr, gv) = noErr) & (BTST(gv, gestaltLaunchControl)) then begin
  299.             if (GetCurrentProcess(ourpsn) = noErr) & (GetFrontProcess(frontpsn) = noErr) then begin
  300.                 if SameProcess(ourpsn, frontpsn, front) = noErr then
  301.                     in_foreground := front;
  302.             end;
  303.         end;
  304.         InForeground := in_foreground;
  305.     end;
  306.  
  307.     function GetWRC (wp: windowPtr): WObject;
  308.         var
  309.             rc: longInt;
  310.     begin
  311.         rc := 0;
  312.         if (wp <> nil) & (windowPeek(wp)^.windowKind >= 0) then begin
  313.             if ((windowPeek(wp)^.windowKind = dialogKind) & (myDialogPtr(wp)^.magic = OOMagic)) | (myWindowPtr(wp)^.magic = OOMagic) then
  314.                 rc := GetWRefCon(wp);
  315.         end;
  316.         if rc = 0 then begin
  317.             default_object.window := wp;
  318.             rc := longInt(default_object);
  319.         end;
  320.         GetWRC := WObject(rc);
  321.     end;
  322.  
  323.     function GetWType (wp: windowPtr): OSType;
  324.         var
  325.             wo: WObject;
  326.     begin
  327.         wo := GetWRC(wp);
  328.         if wo.is_default_object then
  329.             GetWType := WT_NotMine
  330.         else
  331.             GetWType := wo.window_type;
  332.     end;
  333.  
  334.     function GetWObject (wp: windowPtr): WObject;
  335.     begin
  336.         GetWObject := GetWRC(wp);
  337.     end;
  338.  
  339.     function FindWindowID (id: longInt): WObject;
  340.         const
  341.             WindowList = $9D6;
  342.         type
  343.             WindowPtrPtr = ^WindowPtr;
  344.         var
  345.             w: windowPtr;
  346.             wo: WObject;
  347.     begin
  348.         FindWindowID := nil;
  349.         if id <> bad_window_id then begin
  350.             w := WindowPtrPtr(WindowList)^;
  351.             while w <> nil do begin
  352.                 wo := GetWObject(w);
  353.                 if (not wo.is_default_object) & (wo.window_id = id) then begin
  354.                     FindWindowID := wo;
  355.                     leave;
  356.                 end;
  357.                 w := windowPtr(windowPeek(w)^.nextWindow);
  358.             end;
  359.         end;
  360.     end;
  361.  
  362.     function GetDObject (dlg: dialogPtr): DObject;
  363.     begin
  364.         GetDObject := DObject(GetWRC(dlg));
  365.     end;
  366.  
  367.     function FrontObject: WObject;
  368.     begin
  369.         FrontObject := GetWRC(FrontWindow);
  370.     end;
  371.  
  372.     function IsWObjectFront (o: WObject): boolean;
  373.     begin
  374.         if o = nil then
  375.             IsWObjectFront := false
  376.         else if o.window = nil then
  377.             IsWObjectFront := false
  378.         else
  379.             IsWObjectFront := o.window = FrontWindow;
  380.     end;
  381.  
  382.     function WObject.DoSetupDrag (dragref: DragReference; dragrgn: RgnHandle): OSErr;
  383.     begin
  384.         DoSetupDrag := -1;
  385.     end;
  386.  
  387.     procedure WObject.DoTrackDrag (var er: EventRecord);
  388.         var
  389.             err: OSErr;
  390.             dragref: DragReference;
  391.             dragrgn: RgnHandle;
  392.     begin
  393.         drag_obj := self;
  394.         err := NewDrag(dragref);
  395.         if err = noErr then begin
  396.             dragrgn := NewRgn;
  397.             err := MemError;
  398.             if err = noErr then begin
  399.                 err := DoSetupDrag(dragref, dragrgn);
  400.                 if err = noErr then begin
  401.                     err := SetDragSendProc(dragref, @MyDragSendProc, nil);
  402.                 end;
  403.                 if err = noErr then begin
  404.                     err := TrackDrag(dragref, er, dragrgn);
  405.                 end;
  406.                 DisposeRgn(dragrgn);
  407.             end;
  408.             err := DisposeDrag(dragref);
  409.         end;
  410.     end;
  411.  
  412.     function WObject.SaveChanges: SCType;
  413.         var
  414.             a: integer;
  415.             title: str255;
  416.     begin
  417.         SelectWindow(window);
  418.         GetWTitle(window, title);
  419.         if quitNow then begin
  420.             ParamText(title, GetGlobalString(quiting_str), '', '');
  421.         end
  422.         else begin
  423.             ParamText(title, GetGlobalString(closing_str), '', '');
  424.         end;
  425.         SetCursor(arrow);
  426.         a := CautionAlert(save_changes_alert_id, @CancelDiscardModalFilter);
  427.         SaveChanges := SCType(a - 1);
  428.     end;
  429.  
  430.     function WObject.EditMenuEnabled: boolean;
  431.     begin
  432.         if window = nil then
  433.             EditMenuEnabled := false
  434.         else
  435.             EditMenuEnabled := windowPeek(window)^.windowKind < 0
  436.     end;
  437.  
  438.     function WObject.SetMenuBar: boolean;
  439.         var
  440.             oldEditEnabled, editEnabled: boolean;
  441.     begin
  442.         oldEditEnabled := GetIDItemEnable(M_Edit, 0);
  443.         editEnabled := FrontObject.EditMenuEnabled or edit_menu_always_enabled;
  444.         if editEnabled <> oldEditEnabled then
  445.             SetIDItemEnable(M_Edit, 0, editEnabled);
  446.         SetMenuBar := editEnabled <> oldEditEnabled;
  447.     end;
  448.  
  449.     procedure WObject.SetMenus;
  450.     begin
  451.         SetFMenus;
  452.     end;
  453.  
  454.     procedure WObject.SetEditMenuItem (item: integer);
  455.     begin
  456.         if not EditMenuEnabled then
  457.             SetIDItemEnable(M_Edit, item, false);
  458.     end;
  459.  
  460.     procedure WObject.DoEditMenu (item: integer);
  461.         var
  462.             dummyb: boolean;
  463.     begin
  464.         if item <= 6 then
  465.             dummyb := SystemEdit(item - 1);
  466.     end;
  467.  
  468.     function WObject.GetAESelection (var reply: AppleEvent): OSErr;
  469.     begin
  470.         GetAESelection := errAENoUserSelection;
  471.     end;
  472.  
  473.     function WObject.GetAEWindow (var windowrec: AERecord): OSErr;
  474.         var
  475.             err, junk: OSErr;
  476.             s: str255;
  477.             r: rect;
  478.     begin
  479.         AECreate(windowrec);
  480.         if is_default_object then begin
  481.             err := errAEDescNotFound;
  482.         end
  483.         else begin
  484.             err := AECreateList(nil, 0, true, windowrec);
  485.             GetWTitle(window, s);
  486.             if err = noErr then begin
  487.                 junk := PutStringToAERecord(windowrec, pName, s);
  488.                 r := window^.portRect;
  489.                 SetPort(window);
  490.                 LocalToGlobal(r.topleft);
  491.                 LocalToGlobal(r.botright);
  492.                 junk := AEPutKeyPtr(windowrec, pBounds, typeQDRectangle, @r, SizeOf(r));
  493.                 junk := AEPutKeyPtr(windowrec, pPosition, typeQDPoint, @r.topleft, SizeOf(r.topleft));
  494.             end;
  495.         end;
  496.         GetAEWindow := err;
  497.     end;
  498.  
  499.     function WObject.DoMenuKey (er: eventRecord; ch: char): longInt;
  500.         const
  501.             kMaskVirtualKey = $0000FF00; {get virtual key from event message}
  502.             kMaskASCII1 = $00FF0000;
  503.             kMaskASCII2 = $000000FF; {get key from KeyTrans return}
  504.             kKeyUpMask = $0080;
  505.         var
  506.             h: handle;
  507.             virtualKey, keyCId, state, keyInfo: longInt;
  508.             keycode: integer;
  509.             lowchar, highchar: integer;
  510.     begin
  511.         if BAND(er.modifiers, optionKey) <> 0 then begin
  512.             virtualKey := BSR(BAND(er.message, kMaskVirtualKey), 8);
  513.             keyCode := BOR(BOR(BXOR(er.modifiers, optionKey), kKeyUpMask), virtualKey);
  514.             state := 0;
  515.  
  516.             keyCId := GetScript(GetEnvirons(smKeyScript), smScriptKeys);
  517.             h := GetResource('KCHR', keyCId);
  518.  
  519.             if h <> nil then begin
  520.                 HLock(h); { KeyTrans won't move memory, but lock it anyway to avoid any purgine or foolishness }
  521.                 keyInfo := KeyTrans(h^, keyCode, state);
  522.                 ReleaseResource(h);
  523.                 LowChar := BAND(keyInfo, $FF);
  524.                 HighChar := BAND(BSR(keyInfo, 16), $FF);
  525.                 if lowChar <> 0 then
  526.                     ch := chr(lowChar);
  527.                 if highChar <> 0 then
  528.                     ch := chr(highChar);
  529.             end;
  530.         end;
  531.         DoMenuKey := MenuKey(ch);
  532.     end;
  533.  
  534.     procedure WObject.CalculateRegion (var rgn: rgnHandle);
  535.     begin
  536.         SetCursor(arrow);
  537.         rgn := nil;
  538.     end;
  539.  
  540.     function WObject.WaitForEvent (var er: eventRecord; sleep: longInt): boolean;
  541.         var
  542.             rgn: rgnHandle;
  543.             b: boolean;
  544.     begin
  545.         CalculateRegion(rgn);
  546.         WaitForEvent := WaitNextEvent(everyEvent, er, sleep, rgn);
  547.         if rgn <> nil then
  548.             DisposeRgn(rgn);
  549.     end;
  550.  
  551.     procedure WObject.DoDiskEvent (message: longInt);
  552.         var
  553.             pt: point;
  554.             oe: OSErr;
  555.     begin
  556.         if (HiWord(message) <> noErr) then begin
  557.             pt.h := ((screenbits.bounds.Right - screenbits.bounds.Left - 304) div 2);
  558.             pt.v := ((screenbits.bounds.Bottom - screenbits.bounds.Top - 156) div 3);
  559.             InitCursor;
  560.             oe := DIBadMount(pt, message);
  561.         end;
  562.     end;
  563.  
  564.     procedure WObject.DoSuspendResume (resume: boolean);
  565.     begin
  566.         in_foreground := resume;
  567.         if FrontWindow <> nil then begin
  568.             FrontObject.DoActivateDeactivate(resume);
  569.         end;
  570.         InitCursor;
  571.     end;
  572.  
  573.     procedure WObject.DoHighLevel (er: eventRecord);
  574.         var
  575.             oe: OSErr;
  576.     begin
  577.         if has_AppleEvents then
  578.             oe := AEProcessAppleEvent(er);
  579.     end;
  580.  
  581.     procedure WObject.JointCreate (id: integer); { Called for DefaultObject too! }
  582.     begin
  583.         MoveHHi(handle(self));
  584.         HLock(handle(self));
  585.         AppleGuideWindowType := '';
  586.         if window <> nil then begin
  587.             SetWRefCon(window, ord(self));
  588.             GetWindowRect(window, unzoomed);
  589.         end;
  590.         zoomed := false;
  591.         close_hides_window := false;
  592.         SetRect(growRect, 63, 61, 25000, 25000);
  593.         zoomSize.h := 30000;
  594.         zoomSize.v := 30000;
  595.         window_type := WT_Generic;
  596.         draw_grow_icon := false;
  597.         window_id := last_window_id;
  598.         last_window_id := last_window_id + 1;
  599.         resid := id;
  600.         is_default_object := false;
  601.     end;
  602.  
  603.     procedure WObject.CreateBehind (id: integer; behind: WindowPtr);
  604.         var
  605.             wp: myWindowPtr;
  606.     begin
  607.         wp := myWindowPtr(NewPtr(SizeOf(myWindowRecord)));
  608.         wp^.magic := OOMagic;
  609.         window := GetNewWindow(id, ptr(wp), behind);
  610.         JointCreate(id);
  611.     end;
  612.  
  613.     procedure WObject.Create (id: integer);
  614.     begin
  615.         CreateBehind(id, POINTER(-1));
  616.     end;
  617.  
  618.     procedure WObject.Destroy;
  619.     begin
  620.         if (window <> nil) & (GetWType(window) <> WT_NotMine) then begin
  621.             myWindowPtr(window)^.magic := BadOOMagic;
  622.             DisposeWindow(window);
  623.             dispose(self);
  624.         end;
  625.     end;
  626.  
  627.     type
  628.         savedWindowRecord = record
  629.                 windowpos: rect; { the window position }
  630.                 windowvis: rect; { the visible part of the title bar }
  631.                 zoomed: boolean;
  632.                 visible: boolean;
  633.             end;
  634.         savedWindowPtr = ^savedWindowRecord;
  635.         savedWindowHandle = ^savedWindowPtr;
  636.  
  637.     procedure WObject.GetWindowPos (h: handle);
  638.         var
  639.             rgn: RgnHandle;
  640.             r1, r2, global_portrect: rect;
  641.     begin
  642.         HUnlock(h);
  643.         SetHandleSize(h, SizeOf(savedWindowRecord));
  644.         HLock(h);
  645.         with savedWindowHandle(h)^^ do begin
  646.             SetPort(window);
  647.             visible := windowPeek(window)^.visible;
  648.             GetWindowPortRect(window, global_portrect);
  649.             LocalToGlobal(global_portrect.topleft);
  650.             LocalToGlobal(global_portrect.botright);
  651.             windowpos := global_portrect;
  652.             windowpos.top := windowpos.top - titlebar_hight; { title bar }
  653.             rgn := NewRgn;
  654.             RectRgn(rgn, windowpos);
  655.             SectRgn(GetGrayRgn, rgn, rgn);
  656.             windowvis := rgn^^.rgnBBox;
  657.             DisposeRgn(rgn);
  658.             r1 := global_portrect;
  659.             GetWindowStandardState(window, r2);
  660.             InsetRect(r1, -7, -7);
  661.             zoomed := PtInRect(r2.topLeft, r1) and PtInRect(r2.botRight, r1);
  662.         end;
  663.         HUnlock(h);
  664.     end;
  665.  
  666.     procedure WObject.SetWindowPos (h: handle; var wasvisible: boolean);
  667.         var
  668.             rgn: RgnHandle;
  669.             r: rect;
  670.             dummy: boolean;
  671.     begin
  672.         if (h <> nil) & (GetHandleSize(h) = SizeOf(savedWindowRecord)) then begin
  673.             HLock(h);
  674.             with savedWindowHandle(h)^^ do begin
  675.                 wasvisible := visible;
  676.                 rgn := NewRgn;
  677.                 RectRgn(rgn, windowvis);
  678.                 SectRgn(GetGrayRgn, rgn, rgn);
  679.                 r := rgn^^.rgnBBox;
  680.                 DisposeRgn(rgn);
  681.                 dummy := SectRect(r, windowvis, r);
  682.                 if (longInt(r.topleft) = longInt(windowvis.topleft)) & (longInt(r.botright) = longInt(windowvis.botright)) then begin
  683.                     with windowpos do begin
  684.                         MoveWindow(window, left, top + titlebar_hight, true);
  685.                         SizeWindow(window, right - left, bottom - top - titlebar_hight, true);
  686.                     end;
  687.                 end;
  688.                 if zoomed then begin
  689.                     Zoom(true, false);
  690.                 end
  691.                 else begin
  692.                     Resize;
  693.                 end;
  694.             end;
  695.             HUnlock(h);
  696.         end
  697.         else
  698.             wasvisible := true;
  699.     end;
  700.  
  701.     procedure WObject.DoClose;
  702.     begin
  703.         if close_hides_window then begin
  704.             HideWindow(window);
  705.         end
  706.         else begin
  707.             Destroy;
  708.         end;
  709.     end;
  710.  
  711.     procedure WObject.DoContent (er: eventRecord);
  712.     begin
  713.     end;
  714.  
  715.     procedure WObject.DoKey (modifiers: integer; ch: char; code: integer);
  716.     begin
  717.         SysBeep(1);
  718.     end;
  719.  
  720.     procedure WObject.DoSpecialKey (modifiers: integer; ch: char; code: integer);
  721.         var
  722.             item: integer;
  723.     begin
  724.         item := -1;
  725.         if not system7 then begin
  726.             case code of
  727.                 undoKey: 
  728.                     item := EMundo;
  729.                 cutKey: 
  730.                     item := EMcut;
  731.                 copyKey: 
  732.                     item := EMcopy;
  733.                 pasteKey: 
  734.                     item := EMpaste;
  735.                 clearKey: 
  736.                     item := EMclear;
  737.                 otherwise
  738.                     ;
  739.             end;
  740.         end;
  741.         if item <> -1 then begin
  742.             SetMenus;
  743.             if not GetIDItemEnable(M_Edit, 0) or not GetIDItemEnable(M_Edit, item) then
  744.                 item := -1;
  745.         end;
  746.         if item = -1 then
  747.             DoKey(modifiers, ch, code)
  748.         else
  749.             DoMenu(M_Edit, item, domenup);
  750.     end;
  751.  
  752.     procedure WObject.DoAutoKey (modifiers: integer; ch: char; code: integer);
  753.     begin
  754.         DoKey(modifiers, ch, code);
  755.     end;
  756.  
  757.     procedure WObject.DoDrag (where: point);
  758.         var
  759.             temprect: rect;
  760.     begin
  761.         SetPort(window);
  762.         tempRect := GetGrayRgn^^.rgnBBox;
  763.         DragWindow(window, where, tempRect);
  764.     end;
  765.  
  766.     procedure WObject.DoGrow (where: point);
  767.         var
  768.             mypt: point;
  769.             oldrect: rect;
  770.             mResult: longInt;
  771.             tempRect: rect;
  772.     begin
  773.         SetPort(window);
  774.         myPt := where;
  775.         GlobalToLocal(myPt);
  776.         GetWindowPortRect(window, oldrect);
  777.         mResult := GrowWindow(window, where, growRect);
  778.         SizeWindow(window, LoWord(mResult), HiWord(mResult), TRUE);
  779.         SetRect(tempRect, 0, myPt.v - 15, myPt.h + 15, myPt.v + 15);
  780.         EraseRect(tempRect);
  781.         InvalRect(tempRect);
  782.         SetRect(tempRect, myPt.h - 15, 0, myPt.h + 15, myPt.v + 15);
  783.         EraseRect(tempRect);
  784.         InvalRect(tempRect);
  785.         zoomed := false;
  786.         Resize;
  787.     end;
  788.  
  789.     procedure WObject.Zoom (zoomout: boolean; fullscreen: boolean);
  790.         var
  791.             zoompt: Point;
  792.     begin
  793.         if fullscreen then begin
  794.             SetPt(zoompt, 30000, 30000);
  795.         end
  796.         else begin
  797.             zoompt := zoomSize;
  798.         end;
  799.         zoompt.h := Max(zoompt.h, growRect.left);
  800.         zoompt.v := Max(zoompt.v, growRect.top);
  801.         ZoomTheWindow(window, zoomout, zoompt, unzoomed);
  802.         Resize;
  803.         zoomed := zoomout;
  804.     end;
  805.  
  806.     procedure WObject.DoZoom (where: point; code: integer);
  807.     begin
  808.         SetPort(window);
  809.         if TrackBox(window, where, code) then begin
  810.             Zoom(not zoomed, last_event_had_option);
  811.         end;
  812.     end;
  813.  
  814.     procedure WObject.InitialZoom (h, v: integer);
  815.         var
  816.             old: Point;
  817.             r: rect;
  818.     begin
  819.         Resize;
  820.         old := zoomSize;
  821.         if h <> 0 then begin
  822.             zoomSize.h := h;
  823.         end;
  824.         if v <> 0 then begin
  825.             zoomSize.v := v;
  826.         end;
  827.         Zoom(true, false);
  828.         zoomSize := old;
  829.         zoomed := false;
  830.         GetWindowRect(window, unzoomed);
  831.     end;
  832.  
  833.     procedure WObject.DoGoAway (where: point);
  834.     begin
  835.         if TrackGoAway(window, where) then begin
  836.             DoCloseAll(last_event_had_option);
  837.         end;
  838.     end;
  839.  
  840.     procedure WObject.DoUpdate;
  841.         var
  842.             r: rect;
  843.     begin
  844.         BeginUpdate(window);
  845.         Draw;
  846.         EndUpdate(window);
  847.     end;
  848.  
  849.     procedure WObject.TextChanged;
  850.     begin
  851.     end;
  852.  
  853.     procedure WObject.DoMouseMoved (where: point);
  854.     begin
  855.     end;
  856.  
  857.     procedure WObject.DrawGrow;
  858.     begin
  859.         DrawGrowIcon(window);
  860.     end;
  861.  
  862.     procedure WObject.DoActivateDeactivate (activate: boolean);
  863.     begin
  864.         Assert(window <> nil);
  865.         is_active := activate and windowPeek(window)^.visible;
  866.         if is_active then
  867.             SelectWindow(window);
  868.         if draw_grow_icon then
  869.             DrawGrow;
  870.     end;
  871.  
  872.     procedure WObject.Resize;
  873.     begin
  874.         if draw_grow_icon then
  875.             DrawGrow;
  876.     end;
  877.  
  878.     procedure WObject.Draw;
  879.     begin
  880.         if draw_grow_icon then
  881.             DrawGrow;
  882.     end;
  883.  
  884.     function WObject.DoIsDialogEvent (er: eventRecord): boolean;
  885.     begin
  886.         DoIsDialogEvent := IsDialogEvent(er);
  887.     end;
  888.  
  889.     function WObject.DoDialogSelect (er: eventRecord; var dlg: dialogPtr; var item: integer): boolean;
  890.     begin
  891.         DoDialogSelect := DialogSelect(er, dlg, item);
  892.     end;
  893.  
  894.     procedure WObject.DoIdle;
  895.     begin
  896.     end;
  897.  
  898.     function WObject.DoMainClick (er: eventRecord; wp: windowPtr; code: integer): boolean;
  899.         var
  900.             b: boolean;
  901.             mResult: longInt;
  902.             needsselect: boolean;
  903.     begin
  904.         b := false;
  905.         needsselect := (wp <> nil) & (wp <> FrontWindow);
  906.         if needsselect & not (code in [inDrag, inContent]) then begin
  907.             SelectWindow(wp);
  908.         end;
  909.         case code of
  910.             inMenuBar:  begin
  911.                 SetMenus;
  912.                 mResult := MenuSelect(er.where);
  913.                 if mResult <> 0 then
  914.                     DoMenu(HiWord(mResult), LoWord(mResult), domenup);
  915.                 if not quitNow then begin
  916.                     HiliteMenu(0);
  917.                 end;
  918.             end;
  919.             InDrag:  begin
  920.                 if needsselect and (BAND(er.modifiers, cmdKey) = 0) then begin
  921.                     SelectWindow(wp);
  922.                 end;
  923.                 DoDrag(er.where);
  924.             end;
  925.             inGrow: 
  926.                 DoGrow(er.where);
  927.             inZoomIn, inZoomOut: 
  928.                 DoZoom(er.where, code);
  929.             inGoAway: 
  930.                 DoGoAway(er.where);
  931.             inContent:  begin
  932.                 if needsselect then begin
  933.                     SelectWindow(wp);
  934.                 end;
  935.                 DoContent(er);
  936.             end;
  937.             inSysWindow: 
  938.                 SystemClick(er, window);
  939.             otherwise
  940.                 b := true;
  941.         end;
  942.         DoMainClick := b;
  943.     end;
  944.  
  945.     function WObject.HandleSimpleEvents (er: eventRecord): boolean;
  946.         var
  947.             b: boolean;
  948.             ch: char;
  949.             mResult: longInt;
  950.             code: integer;
  951.             wp: WindowPtr;
  952.     begin
  953.         b := false;
  954.         case er.what of
  955.             MouseDown:  begin
  956.                 code := FindWindow(er.where, wp);
  957.                 if wp = nil then begin
  958.                     wp := FrontWindow;
  959.                 end;
  960.                 b := GetWObject(wp).DoMainClick(er, wp, code);
  961.             end;
  962.  
  963.             KeyDown:  begin
  964.                 ch := chr(BAND(er.message, CharCodeMask));
  965.                 mResult := 0;
  966.                 if BAND(er.modifiers, CmdKey) <> 0 then begin
  967.                     SetMenus;
  968.                     mResult := DoMenuKey(er, ch);
  969.                 end;
  970.                 if mResult <> 0 then begin
  971.                     DoMenu(HiWord(mResult), LoWord(mResult), domenup);
  972.                 end
  973.                 else begin
  974.                     DoSpecialKey(er.modifiers, ch, BAND(er.message, keyCodeMask) div $100);
  975.                 end;
  976.             end;
  977.  
  978.             AutoKey: 
  979.                 DoAutoKey(er.modifiers, chr(BAND(er.message, CharCodeMask)), BAND(er.message, keyCodeMask) div $100);
  980.  
  981.             UpdateEvt: 
  982.                 GetWObject(windowPtr(er.message)).DoUpdate;
  983.  
  984.             ActivateEvt: 
  985.                 GetWObject(windowPtr(er.message)).DoActivateDeactivate(odd(er.modifiers));
  986.  
  987.             kOSEvent: 
  988.                 if BAND(BROTL(er.message, 8), $FF) = kSuspendResumeMessage then begin
  989.                     DoSuspendResume(BAnd(er.message, kResumeMask) <> 0);
  990.                 end
  991.                 else if BAND(BROTL(er.message, 8), $FF) = kMouseMovedMessage then begin
  992.                     DoMouseMoved(er.where);
  993.                 end
  994.                 else begin
  995.                     b := true;
  996.                 end;
  997.  
  998.             kHighLevelEvent: 
  999.                 DoHighLevel(er);
  1000.  
  1001.             DiskEvt: 
  1002.                 DoDiskEvent(er.message);
  1003.  
  1004.             otherwise
  1005.                 b := true;
  1006.         end;
  1007.         HandleSimpleEvents := b;
  1008.     end;
  1009.  
  1010.     function WObject.HandleEvents (er: eventRecord): boolean;
  1011.         var
  1012.             b: boolean;
  1013.             dlg: dialogPtr;
  1014.             item: integer;
  1015.     begin
  1016.         last_event_time := er.when;
  1017.         last_event_modifers := er.modifiers;
  1018.         last_event_had_option := BAND(er.modifiers, optionKey) <> 0;
  1019.         last_event_had_command := BAND(er.modifiers, cmdKey) <> 0;
  1020.         last_event_had_shift := BAND(er.modifiers, shiftKey) <> 0;
  1021.         last_event_had_control := BAND(er.modifiers, controlKey) <> 0;
  1022.         DoIdle;
  1023.         b := true;
  1024.         if DoIsDialogEvent(er) then begin
  1025.             if DoDialogSelect(er, dlg, item) then begin
  1026.                 GetDObject(dlg).DoItemWhere(er, item);
  1027.                 b := false;
  1028.             end;
  1029.         end;
  1030.         if b then begin
  1031.             b := HandleSimpleEvents(er);
  1032.         end;
  1033.         HandleEvents := b;
  1034.     end;
  1035.  
  1036.     procedure DObject.CreateBehind (id: integer; behind: WindowPtr);
  1037.         var
  1038.             wp: myDialogPtr;
  1039.     begin
  1040.         disable_edit_menu := false;
  1041.         wp := myDialogPtr(NewPtr(SizeOf(myDialogRecord)));
  1042.         wp^.magic := OOMagic;
  1043.         window := GetNewDialog(id, ptr(wp), behind);
  1044.         ok_item := 0;
  1045.         cancel_item := 0;
  1046.         handle_activate_outline := false;
  1047.         handle_shift_tab := true;
  1048.         JointCreate(id);
  1049.     end;
  1050.  
  1051.     procedure DObject.Create (id: integer);
  1052.     begin
  1053.         CreateBehind(id, POINTER(-1));
  1054.     end;
  1055.  
  1056.     procedure DObject.Destroy;
  1057.     begin
  1058.         if (window <> nil) & (GetWType(window) <> WT_NotMine) then begin
  1059.             myDialogPtr(window)^.magic := BadOOMagic;
  1060.             DisposDialog(window);
  1061.             dispose(self);
  1062.         end;
  1063.     end;
  1064.  
  1065.     procedure OODrawOutline (dp: dialogPtr; item: integer);
  1066.         var
  1067.             r: rect;
  1068.             fi: DObject;
  1069.             pstate: PenState;
  1070.     begin
  1071.         SetPort(dp);
  1072.         GetPenState(pstate);
  1073.         fi := DObject(GetWObject(dp));
  1074.         GetDItemRect(dp, fi.ok_item, r);
  1075.         InsetRect(r, -4, -4);
  1076.         PenSize(3, 3);
  1077.         if not GetDCtlEnable(dp, fi.ok_item) or not fi.is_active then begin
  1078.             PenPat(gray);
  1079.             FrameRoundRect(r, 16, 16);
  1080.             PenPat(black);
  1081.         end
  1082.         else
  1083.             FrameRoundRect(r, 16, 16);
  1084.         SetPenState(pstate);
  1085.     end;
  1086.  
  1087.     procedure DObject.DrawOutline;
  1088.     begin
  1089.         OODrawOutline(window, ok_item);
  1090.     end;
  1091.  
  1092.     procedure DObject.SetOOOutline (def_item, user_item: integer);
  1093.         var
  1094.             kind: integer;
  1095.             h: handle;
  1096.             r: rect;
  1097.     begin
  1098.         handle_activate_outline := true;
  1099.         ok_item := def_item;
  1100.         GetDItem(window, user_item, kind, h, r);
  1101.         InsetRect(r, -10, -10);
  1102.         SetDItem(window, user_item, userItem, handle(@OODrawOutline), r);
  1103.     end;
  1104.  
  1105.     procedure DObject.DoActivateDeactivate (activate: boolean);
  1106.     begin
  1107.         inherited DoActivateDeactivate(activate);
  1108.         if handle_activate_outline then
  1109.             OODrawOutline(window, 0);
  1110.     end;
  1111.  
  1112.     procedure DObject.DoOK (modifiers: integer; ch: char; code: integer);
  1113.     begin
  1114.         if ok_item = 0 then
  1115.             DoKey(modifiers, ch, code)
  1116.         else begin
  1117.             if GetDCtlEnable(window, ok_item) then begin
  1118.                 FlashDItem(window, ok_Item);
  1119.                 DoItem(ok_item);
  1120.             end;
  1121.         end;
  1122.     end;
  1123.  
  1124.     procedure DObject.DoCancel (modifiers: integer; ch: char; code: integer);
  1125.     begin
  1126.         if cancel_item = 0 then
  1127.             DoKey(modifiers, ch, code)
  1128.         else begin
  1129.             FlashDItem(window, cancel_Item);
  1130.             DoItem(cancel_item);
  1131.         end;
  1132.     end;
  1133.  
  1134.     procedure DObject.DoItem (item: integer);
  1135.     begin
  1136.     end;
  1137.  
  1138.     procedure DObject.DoItemWhere (er: eventRecord; item: integer);
  1139.     begin
  1140.         DoItem(item);
  1141.     end;
  1142.  
  1143.     function DObject.HandleEvents (er: eventRecord): boolean;
  1144.         var
  1145.             b: boolean;
  1146.             ch: char;
  1147.     begin
  1148.         b := true;
  1149.         if ((er.what = KeyDown) or (er.what = AutoKey)) then begin
  1150.             b := false;
  1151.             ch := chr(BAND(er.message, charCodeMask));
  1152.             if (ch = chr(13)) or (ch = chr(3)) then begin
  1153.                 DoOK(er.modifiers, ch, BAND(er.message, keyCodeMask) div $100);
  1154.             end
  1155.             else if (ch = chr(27)) or ((ch = '.') and (BAND(er.modifiers, cmdKey) <> 0)) then begin
  1156.                 DoCancel(er.modifiers, ch, BAND(er.message, keyCodeMask) div $100);
  1157.             end
  1158.             else if (ch = tab) and (BAND(er.modifiers, shiftKey) <> 0) then begin
  1159.                 if handle_shift_tab then begin
  1160.                     ShiftTab(window);
  1161.                 end
  1162.                 else begin
  1163.                     b := true;
  1164.                 end;
  1165.             end
  1166.             else begin
  1167.                 b := true;
  1168.             end;
  1169.         end;
  1170.         if b then begin
  1171.             b := inherited HandleEvents(er);
  1172.         end;
  1173.         HandleEvents := b;
  1174.     end;
  1175.  
  1176.     procedure DObject.SetEditMenuItem (item: integer);
  1177.     begin
  1178.         if is_default_object or disable_edit_menu or (SelectedTextItem(window) <= 0) then begin
  1179.             SetIDItemEnable(M_Edit, item, false);
  1180.         end
  1181.         else begin
  1182.             TESetEditMenuItem(dialogPeek(window)^.textH, false, 250, item);
  1183.         end;
  1184.     end;
  1185.  
  1186.     function DObject.EditMenuEnabled: boolean;
  1187.     begin
  1188.         if is_default_object or disable_edit_menu or (SelectedTextItem(window) <= 0) then begin
  1189.             EditMenuEnabled := false;
  1190.         end
  1191.         else begin
  1192.             EditMenuEnabled := TEEditMenuEnabled(dialogPeek(window)^.textH, false, 250);
  1193.         end;
  1194.     end;
  1195.  
  1196.     procedure DObject.DoEditMenu (item: integer);
  1197.         var
  1198.             loe: longInt;
  1199.             oe: OSErr;
  1200.     begin
  1201.         case item of
  1202.             EMUndo: 
  1203.                 ;
  1204.             EMCut:  begin
  1205.                 DlgCut(window);
  1206.                 loe := ZeroScrap;
  1207.                 oe := TEToScrap;
  1208.                 TextChanged;
  1209.             end;
  1210.             EMCopy:  begin
  1211.                 DlgCopy(window);
  1212.                 loe := ZeroScrap;
  1213.                 oe := TEToScrap;
  1214.             end;
  1215.             EMPaste:  begin
  1216.                 oe := TEFromScrap;
  1217.                 DlgPaste(window);
  1218.                 TextChanged;
  1219.             end;
  1220.             EMClear:  begin
  1221.                 DlgDelete(window);
  1222.                 TextChanged;
  1223.             end;
  1224.             EMSelectAll:  begin
  1225.                 if (SelectedTextItem(window) > 0) then begin
  1226.                     SelIText(window, SelectedTextItem(window), 0, maxInt);
  1227.                 end;
  1228.             end;
  1229.             otherwise
  1230.                 ;
  1231.         end;
  1232.     end;
  1233.  
  1234.     function DObject.GetAESelection (var reply: AppleEvent): OSErr;
  1235.         var
  1236.             err: OSErr;
  1237.     begin
  1238.         if not is_default_object & (SelectedTextItem(window) > 0) then begin
  1239.             err := PutTESelectionToAERecord(reply, keyDirectObject, dialogPeek(window)^.textH);
  1240.         end
  1241.         else begin
  1242.             err := errAENoUserSelection;
  1243.         end;
  1244.         GetAESelection := err;
  1245.     end;
  1246.  
  1247.     function DObject.DoIsDialogEvent (er: eventRecord): boolean;
  1248.     begin
  1249.         if ((er.what = keyDown) or (er.what = autoKey)) and (BAND(er.modifiers, cmdKey) <> 0) then begin
  1250.             DoIsDialogEvent := false; { Stop system 7 from doing the edit menu as well }
  1251.         end
  1252.         else begin
  1253.             DoIsDialogEvent := inherited DoIsDialogEvent(er);
  1254.         end;
  1255.     end;
  1256.  
  1257. end.